package com.tsvetanv.simpleformcontroller.example01.person.mvc.controller;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;

import com.tsvetanv.simpleformcontroller.example01.person.mvc.model.Person;
import com.tsvetanv.simpleformcontroller.example01.person.mvc.model.ProgrammingLanguage;
import com.tsvetanv.simpleformcontroller.example01.person.mvc.service.BookService;
import com.tsvetanv.simpleformcontroller.example01.person.mvc.service.PersonService;

public class PersonFormController extends SimpleFormController {
	private Logger logger = Logger.getLogger(PersonFormController.class);

	protected PersonService personService;
	protected BookService bookService;

	// --- Constructor, Getter/Setter ------------------------------------------
	public PersonFormController() {
		setCommandName("person");
		setCommandClass(Person.class);
		setFormView("simple-form-controller/personFormPage");
		setSuccessView("simple-form-controller/successPersonPage");
	}

	public PersonService getPersonService() {
		return personService;
	}

	public void setPersonService(PersonService personService) {
		this.personService = personService;
	}

	public BookService getBookService() {
		return bookService;
	}

	public void setBookService(BookService bookService) {
		this.bookService = bookService;
	}

	// --- Methods -------------------------------------------------------------

	/**
	 * Override initBinder to add a custom DataBinder for Date form data
	 */
	@Override
	protected void initBinder(HttpServletRequest request,
			ServletRequestDataBinder binder) throws Exception {

		// TODO extract the Date format string in an external property file
		CustomDateEditor dateEditor = new CustomDateEditor(
				new SimpleDateFormat("dd-MM-yyyy"), false);
		binder.registerCustomEditor(Date.class, dateEditor);
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	protected Map<String, String[]> referenceData(HttpServletRequest request)
			throws Exception {

		// List<String> languages = new ArrayList<String>();
		// for (ProgrammingLanguage language : ProgrammingLanguage.values()) {
		// languages.add(language.getName());
		// }
		//
		Map dataMap = new HashMap<String, String[]>();
		dataMap.put("languages", ProgrammingLanguage.values());
		return dataMap;
	}

	/*
	 * the doSubmitAction()method is useful when the default success view is
	 * sufficient. When you need to return objects required by the success view,
	 * you will need to implement an onSubmit()method.
	 */
	@Override
	protected void doSubmitAction(Object command) throws Exception {
		logger.info("doSubmitAction executed");

		if (command instanceof Person) {
			personService.savePerson((Person) command);
		}
	}

	@Override
	protected ModelAndView onSubmit(Object command) throws Exception {
		logger.info("onSubmit executed");

		if (!(command instanceof Person)) {
			throw new IllegalArgumentException("Incorrect input object");
		}
		Person person = (Person) command;
		personService.savePerson(person);

		String recommendedBook = bookService.recommendBook(person
				.getProgrammingLanguage());

		Map<String, Object> model = new HashMap<String, Object>();
		// In onSubmit() we are required to manually add the person into the
		// model. It is not automatic as it is in doSubmitAction().
		model.put("person", person);
		model.put("recommendedBook", recommendedBook);

		return new ModelAndView(
				"simple-form-controller/successPersonAndRecommendedBookPage",
				model);

	}

}
